package com.hunit.mqtt_dome.controller;

import com.hunit.mqtt_dome.emqx.MqttAcceptClient;
import com.hunit.mqtt_dome.emqx.MqttSendClient;
import com.hunit.mqtt_dome.properties.MqttProperties;
import com.hunit.mqtt_dome.service.MqttMessageReceiveService;
import com.hunit.mqtt_dome.service.MqttMessageService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description : MQTT消息控制器
 * @Author : Sherlock
 * @Date : 2023/8/1 18:00
 */
@RestController
@RequestMapping("/mqtt")
@Api(tags = "MQTT消息管理", description = "提供MQTT消息发送、接收和主题订阅等功能")
public class MqttController {

    private static final Logger logger = LoggerFactory.getLogger(MqttController.class);

    @Autowired
    private MqttMessageService mqttMessageService;

    @Autowired
    private MqttMessageReceiveService mqttMessageReceiveService;
    
    @Autowired
    private MqttAcceptClient mqttAcceptClient;
    
    @Autowired
    private MqttSendClient mqttSendClient;
    
    @Autowired
    private MqttProperties mqttProperties;

    /**
     * 获取MQTT连接状态
     *
     * @return 连接状态信息
     */
    @GetMapping("/status")
    @ApiOperation(value = "获取MQTT连接状态", notes = "返回MQTT客户端连接状态和配置信息")
    public Map<String, Object> getStatus() {
        Map<String, Object> result = new HashMap<>();
        
        // 获取配置信息
        Map<String, Object> config = new HashMap<>();
        config.put("hostUrl", mqttProperties.getHostUrl());
        config.put("clientId", mqttProperties.getClientId());
        config.put("defaultTopic", mqttProperties.getDefaultTopic());
        config.put("isOpen", mqttProperties.getIsOpen());
        
        result.put("config", config);
        
        // 重新连接接收客户端和发送客户端，获取最新状态
        boolean receiveConnected = mqttAcceptClient.connect();
        boolean sendConnected = mqttSendClient.connect();
        
        result.put("receiveClientConnected", receiveConnected);
        result.put("sendClientConnected", sendConnected);
        result.put("status", (receiveConnected && sendConnected) ? "正常" : "异常");
        
        return result;
    }

    /**
     * 发送消息
     *
     * @param topic 主题
     * @param message 消息内容
     * @return 发送结果
     */
    @PostMapping("/send")
    @ApiOperation(value = "发送普通消息", notes = "发送普通文本消息到指定主题")
    public Map<String, Object> sendMessage(
            @ApiParam(value = "消息主题", required = true) @RequestParam String topic, 
            @ApiParam(value = "消息内容", required = true) @RequestParam String message) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到发送消息请求，主题: {}, 消息: {}", topic, message);
            boolean success = mqttMessageService.sendMessage(topic, message);
            
            result.put("success", success);
            if (success) {
                result.put("message", "消息发送成功");
                result.put("topic", topic);
                result.put("content", message);
            } else {
                result.put("message", "消息发送失败");
            }
        } catch (Exception e) {
            logger.error("发送消息异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "发送异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 发送消息并设置保留标志
     *
     * @param topic 主题
     * @param message 消息内容
     * @param retained 是否保留消息
     * @return 发送结果
     */
    @PostMapping("/sendWithRetain")
    @ApiOperation(value = "发送保留消息", notes = "发送普通文本消息到指定主题，并可设置保留标志")
    public Map<String, Object> sendMessageWithRetain(
            @ApiParam(value = "消息主题", required = true) @RequestParam String topic, 
            @ApiParam(value = "消息内容", required = true) @RequestParam String message, 
            @ApiParam(value = "是否保留消息", defaultValue = "false") @RequestParam(defaultValue = "false") boolean retained) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到发送消息请求，主题: {}, 消息: {}, 保留: {}", topic, message, retained);
            boolean success = mqttMessageService.sendMessage(topic, message, retained);
            
            result.put("success", success);
            if (success) {
                result.put("message", "消息发送成功");
                result.put("topic", topic);
                result.put("content", message);
                result.put("retained", retained);
            } else {
                result.put("message", "消息发送失败");
            }
        } catch (Exception e) {
            logger.error("发送消息异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "发送异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 发送JSON消息
     *
     * @param topic 主题
     * @param payload JSON数据
     * @return 发送结果
     */
    @PostMapping("/sendJson")
    @ApiOperation(value = "发送JSON消息", notes = "发送JSON格式消息到指定主题")
    public Map<String, Object> sendJsonMessage(
            @ApiParam(value = "消息主题", required = true) @RequestParam String topic, 
            @ApiParam(value = "JSON消息内容", required = true) @RequestBody Map<String, Object> payload) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到发送JSON消息请求，主题: {}, 数据: {}", topic, payload);
            boolean success = mqttMessageService.sendJsonMessage(topic, payload);
            
            result.put("success", success);
            if (success) {
                result.put("message", "JSON消息发送成功");
                result.put("topic", topic);
                result.put("payload", payload);
            } else {
                result.put("message", "JSON消息发送失败");
            }
        } catch (Exception e) {
            logger.error("发送JSON消息异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "发送异常: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 发送JSON消息并设置保留标志
     *
     * @param topic 主题
     * @param payload JSON数据
     * @param retained 是否保留消息
     * @return 发送结果
     */
    @PostMapping("/sendJsonWithRetain")
    @ApiOperation(value = "发送保留JSON消息", notes = "发送JSON格式消息到指定主题，并可设置保留标志")
    public Map<String, Object> sendJsonMessageWithRetain(
            @ApiParam(value = "消息主题", required = true) @RequestParam String topic, 
            @ApiParam(value = "是否保留消息", defaultValue = "false") @RequestParam(defaultValue = "false") boolean retained,
            @ApiParam(value = "JSON消息内容", required = true) @RequestBody Map<String, Object> payload) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到发送JSON消息请求，主题: {}, 保留: {}, 数据: {}", topic, retained, payload);
            boolean success = mqttMessageService.sendJsonMessage(topic, payload, retained);
            
            result.put("success", success);
            if (success) {
                result.put("message", "JSON消息发送成功");
                result.put("topic", topic);
                result.put("payload", payload);
                result.put("retained", retained);
            } else {
                result.put("message", "JSON消息发送失败");
            }
        } catch (Exception e) {
            logger.error("发送JSON消息异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "发送异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 订阅主题
     *
     * @param topic 主题
     * @return 订阅结果
     */
    @PostMapping("/subscribe")
    @ApiOperation(value = "订阅主题", notes = "订阅指定的MQTT主题")
    public Map<String, Object> subscribe(
            @ApiParam(value = "要订阅的主题", required = true) @RequestParam String topic) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到订阅主题请求: {}", topic);
            boolean success = mqttMessageReceiveService.subscribe(topic);
            
            result.put("success", success);
            if (success) {
                result.put("message", "主题订阅成功");
                result.put("topic", topic);
            } else {
                result.put("message", "主题订阅失败");
            }
        } catch (Exception e) {
            logger.error("订阅主题异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "订阅异常: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 订阅主题并指定QoS
     *
     * @param topic 主题
     * @param qos QoS级别(0,1,2)
     * @return 订阅结果
     */
    @PostMapping("/subscribeWithQos")
    @ApiOperation(value = "指定QoS订阅主题", notes = "订阅指定的MQTT主题，并设置QoS级别")
    public Map<String, Object> subscribeWithQos(
            @ApiParam(value = "要订阅的主题", required = true) @RequestParam String topic,
            @ApiParam(value = "服务质量等级(0,1,2)", defaultValue = "0") @RequestParam(defaultValue = "0") int qos) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到订阅主题请求: {}, QoS: {}", topic, qos);
            boolean success = mqttMessageReceiveService.subscribe(topic, qos);
            
            result.put("success", success);
            if (success) {
                result.put("message", "主题订阅成功");
                result.put("topic", topic);
                result.put("qos", qos);
            } else {
                result.put("message", "主题订阅失败");
            }
        } catch (Exception e) {
            logger.error("订阅主题异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "订阅异常: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 批量订阅主题
     *
     * @param topics 主题列表，格式为JSON数组
     * @return 订阅结果
     */
    @PostMapping("/batchSubscribe")
    @ApiOperation(value = "批量订阅主题", notes = "一次订阅多个MQTT主题")
    public Map<String, Object> batchSubscribe(
            @ApiParam(value = "主题列表", required = true) @RequestBody List<String> topics) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> details = new ArrayList<>();
        
        try {
            logger.info("接收到批量订阅主题请求: {}", topics);
            boolean allSuccess = true;
            
            for (String topic : topics) {
                Map<String, Object> topicResult = new HashMap<>();
                topicResult.put("topic", topic);
                
                boolean success = mqttMessageReceiveService.subscribe(topic);
                topicResult.put("success", success);
                
                if (!success) {
                    allSuccess = false;
                    topicResult.put("message", "订阅失败");
                } else {
                    topicResult.put("message", "订阅成功");
                }
                
                details.add(topicResult);
            }
            
            result.put("success", allSuccess);
            result.put("message", allSuccess ? "所有主题订阅成功" : "部分主题订阅失败");
            result.put("details", details);
            
        } catch (Exception e) {
            logger.error("批量订阅主题异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "批量订阅异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 取消订阅主题
     *
     * @param topic 主题
     * @return 取消订阅结果
     */
    @PostMapping("/unsubscribe")
    @ApiOperation(value = "取消订阅主题", notes = "取消订阅指定的MQTT主题")
    public Map<String, Object> unsubscribe(
            @ApiParam(value = "要取消订阅的主题", required = true) @RequestParam String topic) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到取消订阅主题请求: {}", topic);
            boolean success = mqttMessageReceiveService.unsubscribe(topic);
            
            result.put("success", success);
            if (success) {
                result.put("message", "取消订阅成功");
                result.put("topic", topic);
            } else {
                result.put("message", "取消订阅失败");
            }
        } catch (Exception e) {
            logger.error("取消订阅主题异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "取消订阅异常: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 重新连接MQTT客户端
     *
     * @return 重连结果
     */
    @PostMapping("/reconnect")
    @ApiOperation(value = "重新连接MQTT", notes = "断开并重新连接MQTT客户端，重新订阅默认主题")
    public Map<String, Object> reconnect() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("接收到重新连接MQTT客户端请求");
            
            // 先断开连接
            mqttAcceptClient.disconnect();
            mqttSendClient.disconnect();
            
            // 重新连接
            boolean acceptConnected = mqttAcceptClient.connect();
            boolean sendConnected = mqttSendClient.connect();
            
            boolean allConnected = acceptConnected && sendConnected;
            
            result.put("success", allConnected);
            result.put("receiveClientConnected", acceptConnected);
            result.put("sendClientConnected", sendConnected);
            result.put("message", allConnected ? "所有客户端重连成功" : "部分客户端重连失败");
            
            // 如果接收客户端连接成功，重新订阅默认主题
            if (acceptConnected) {
                boolean subscribed = mqttMessageReceiveService.subscribe(mqttProperties.getDefaultTopic());
                result.put("defaultTopicResubscribed", subscribed);
            }
            
        } catch (Exception e) {
            logger.error("重连MQTT客户端异常: {}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "重连异常: " + e.getMessage());
        }
        
        return result;
    }
} 